package kz.pvnhome.pimrestore.pim;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import kz.pvnhome.pimrestore.baseutils.StringUtil;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;

/**
 * Created: May 12, 2012 11:06:06 AM
 * @author victor
 */
public class ContactsLoadTask extends AsyncTask<String, Integer, List<ContactDTO>> {
   private static final String TAG = "ContactsLoadTask";

   private ProgressBar mProgress;

   private long size;

   private long pos;

   private ContactsLoadListener loadListener;

   public ContactsLoadTask(ProgressBar mProgress, ContactsLoadListener loadListener) {
      this.mProgress = mProgress;
      this.loadListener = loadListener;
   }

   @Override
   protected List<ContactDTO> doInBackground(String... fileNames) {
      List<ContactDTO> dtos = new ArrayList<ContactDTO>();
      /*
      int count = urls.length;
      long totalSize = 0;
      for (int i = 0; i < count; i++) {
          totalSize += Downloader.downloadFile(urls[i]);
          publishProgress((int) ((i / (float) count) * 100));
      }
      */

      List<SrcRec> srcList = new ArrayList<SrcRec>();
      Map<String, SrcRec> srcMap = new HashMap<String, SrcRec>();

      try {
         String pimFileName = fileNames[0];
         FileInputStream fis = new FileInputStream(pimFileName);
         ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));

         ZipEntry entry;
         while ((entry = zin.getNextEntry()) != null) {
            Log.d(TAG, "FILE: " + entry.getName());
            if (entry.getName().startsWith("contacts_")) {
               Log.d(TAG, "CONTACTS: " + entry.getName());

               size = entry.getSize();
               pos = 0L;

               InputStreamReader isr = new InputStreamReader(zin, "UTF-16");
               BufferedReader br = new BufferedReader(isr);

               String hdr = readNextLine(br);
               if (hdr == null) {
                  Log.d(TAG, "HEADER IS NULL");
               } else {
                  String[] hdrs = hdr.split(";");
                  Log.d(TAG, "HEADER:");
                  for (int i = 0; i < hdrs.length; i++) {
                     checkCanceled();

                     SrcRec rec = new SrcRec(hdrs[i]);
                     Log.d(TAG, "   " + rec.getName());
                     srcList.add(rec);
                     srcMap.put(rec.getName(), rec);
                  }

                  hdr = readNextLine(br);
                  while (hdr != null) {
                     checkCanceled();

                     hdr = hdr.substring(1, hdr.length() - 1);
                     hdrs = hdr.split("\";\"");

                     for (int i = 0; i < hdrs.length; i++) {
                        SrcRec rec = srcList.get(i);
                        String val = hdrs[i];
                        if (val != null && !val.isEmpty()) {
                           if (rec.getName().equals("Notes Ink")) {
                              //Log.d(TAG, rec.getName() + " = " + StringUtil.convertFromHex(rec.getValue()));
                           } else if (rec.getName().equals("Notes")) {
                              if (!val.equals("0x0d,0x00,0x0a,0x00")) {
                                 String notes = StringUtil.convertFromHex(val, ",", "UTF-16LE");
                                 //Log.d(TAG, rec.getName() + " = " + notes);
                                 rec.setValue(notes);
                              } else {
                                 rec.setValue(null);
                              }
                           } else {
                              //Log.d(TAG, rec.getName() + " = " + val);
                              rec.setValue(val);
                           }
                        } else {
                           rec.setValue(null);
                        }
                     }
                     
                     dtos.add(new ContactDTO(srcMap));

                     hdr = readNextLine(br);
                  }

                  Log.d(TAG, "");
                  Log.d(TAG, "COUNTS:");

                  for (int i = 0; i < srcList.size(); i++) {
                     SrcRec rec = srcList.get(i);
                     if (rec.getCnt() > 0) {
                        Log.d(TAG, rec.getName() + " = " + rec.getCnt());
                     }
                  }
               }
            }
         }

         zin.close();
      } catch (TaskCancelationException ce) {
         Log.d(TAG, "ConatactLoadTask canceled"); //$NON-NLS-1$
         dtos = null;
      } catch (Exception e) {
         Log.e(TAG, "doInBackground", e);
         dtos = null;
      }

      return dtos;
   }

   private String readNextLine(BufferedReader br) throws IOException {
      String line = br.readLine();
      if (line != null) {
         pos += line.length();
         long progress = (pos * 100L) / size ;
         publishProgress(progress > 100 ? 100 : (int) progress);
      }
      return line;
   }

   private void checkCanceled() throws TaskCancelationException {
      if (isCancelled()) {
         throw new TaskCancelationException();
      }
   }

   @Override
   protected void onProgressUpdate(Integer... progress) {
      mProgress.setProgress(progress[0]);
   }

   @Override
   protected void onPreExecute() {
      //super.onPreExecute();
      mProgress.setProgress(0);
      mProgress.setVisibility(View.VISIBLE);
   }

   @Override
   protected void onCancelled() {
      mProgress.setVisibility(View.INVISIBLE);
   }

   @Override
   protected void onPostExecute(List<ContactDTO> result) {
      mProgress.setVisibility(View.INVISIBLE);
      if (result == null) {
         Log.d(TAG, "Empty result"); //$NON-NLS-1$
      } else {
         Log.d(TAG, "LOADED"); //$NON-NLS-1$
         loadListener.contactsLoaded(result);
      }
   }
}
